<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 使用 严格模式  普通函数中的this 指向undefined
        // "use strict"
        
        // this  关键字 【出现在函数内部才有意义】   -> 指向取决于函数的调用方式
            // 执行上下文的环境对象  ->  即在不同的环境中 指向不同的内容

        // 在全局【window】环境中的变量和函数 自动挂靠window 成了window的属性【变量】和方法【function】
        // var a = "hello";

        // function b(){
        //     console.log(123)
        //     console.log(this)
        // }
        // console.log(window)

        // console.log(window.a)
        // b()

        // console.log(this)

        // 全局环境:  window
        // 函数上下文: 
            // 1 普通函数 直接调用  window
            // 2 事件程序中         事件源 即 绑定事件的元素
            // 3 在对象中           obj
            // 4 在构造函数中       实例
            // 5 方法的回调函数     window
            // 6 箭头函数          箭头函数没有自己的 this，箭头函数中的 this 指向定义时的父级作用域的 this
            // 总结: 谁调用 指向谁

        // var obj = {
        //     name : "张三" , 
        //     age : 18 , 
        //     say : function(){
        //         console.log(`say hello`)
        //         console.log(this)
        //     },
        //     eat : function(){
        //         console.log(`eat rice`)
        //     }
        // }
        // console.log( obj.name )
        // obj.say()

        // setTimeout( function(){
        //     console.log(this)
        // } , 1000);

        // 
        // var name = 'window'
        // var person = {
        //     name: 'person',
        //     sayName: function () {
        //         console.log(this.name)
        //     }
        // }
        // function sayName () {
        //     var sss = person.sayName;
        //     sss();
        //     person.sayName(); 
        //     (person.sayName)(); 
        //     (b = person.sayName)() 
        // }
        // sayName()


    // var name = 'window'
    // var person1 = {
    //     name: 'person1',
    //     foo1: function () {
    //         console.log(this.name)
    //     },
    //     foo2: () => {
    //         console.log(this.name)
    //     },
    //     foo3: function () {
    //         return function () {
    //             console.log(this.name)
    //         }
    //     },
    //     foo4: function () {
    //         return () => {
    //             console.log(this.name)
    //         }}}
    //         var person2 = { name: 'person2' }
    // 正题来咯
    // person1.foo1(); 
    // person1.foo1.call(person2); 
    // person1.foo2(); 
    // person1.foo2.call(person2);
    // person1.foo3()();
    // person1.foo3.call(person2)(); 
    // person1.foo3().call(person2);
    // person1.foo4()();
    // person1.foo4.call(person2)();
    // person1.foo4().call(person2);



    var name = 'window'
    function Person (name) {
        this.name = name
        this.foo1 = function () {
            console.log(this.name)
        }
        this.foo2 = () => console.log(this.name)
        this.foo3 = function () {
            return function () {
                console.log(this.name)
            }
        }
        this.foo4 = function () {
            return () => { console.log(this.name) }
        }
    }
    var person1 = new Person('person1')
    var person2 = new Person('person2')

    person1.foo1()   //person1
    person1.foo1.call(person2)   //person2
    person1.foo2()               //person1
    person1.foo2.call(person2)   //person1
    person1.foo3()()             //window
    person1.foo3.call(person2)() //window
    person1.foo3().call(person2) //person2
    person1.foo4()()             //person1
    person1.foo4.call(person2)() //person2
    person1.foo4().call(person2) //person1


    </script>
</body>
</html>